package com.zyb.dfs.datanode.server;

import java.io.File;

/**
 * DataNode启动类
 *
 * @author zhonghuashishan
 */
public class DataNode {

    /**
     * 是否还在运行
     */
    private volatile Boolean shouldRun;
    /**
     * 负责跟一组NameNode通信的组件
     */
    private NameNodeOfferService offerService;

    /**
     * 负责跟一组NameNode通信的组件
     */
    private NameNodeRpcClient namenodeRpcClient;

    /**
     * 心跳管理组件
     */
    private HeartbeatManager heartbeatManager;
    /**
     * 磁盘存储管理组件
     */
    private StorageManager storageManager;
    /**
     * 复制任务管理组件
     */
    private ReplicateManager replicateManager;

    /**
     * 初始化DataNode
     */
    private void initialize() throws Exception {
        // this.offerService = new NameNodeOfferService();
        // this.offerService.start();
        this.shouldRun = true;
        this.namenodeRpcClient = new NameNodeRpcClient();
        Boolean result = this.namenodeRpcClient.register();
        if (!result) {
            System.out.println("向NameNode注册失败，直接退出......");
            System.exit(1);
        }
        this.replicateManager = new ReplicateManager(this.namenodeRpcClient);
        this.storageManager = new StorageManager();
        this.heartbeatManager = new HeartbeatManager(
                this.namenodeRpcClient,
                this.storageManager,
                this.replicateManager
        );
        this.heartbeatManager.start();

        StorageInfo storageInfo = this.storageManager.getStorageInfo();
        if (storageInfo != null) {
            this.namenodeRpcClient.reportCompleteStorageInfo(storageInfo);
        }

        DataNodeNIOServer nioServer = new DataNodeNIOServer(namenodeRpcClient);
        nioServer.init();
        nioServer.start();
    }

    /**
     * 获取存储信息
     *
     * @return
     */
    private StorageInfo getStorageInfo() {
        StorageInfo storageInfo = new StorageInfo();

        File dataDir = new File(DataNodeConfig.DATA_DIR);
        File[] children = dataDir.listFiles();
        if (children == null || children.length == 0) {
            return null;
        }

        for (File child : children) {
            scanFiles(child, storageInfo);
        }

        return storageInfo;
    }

    /**
     * 扫描文件
     *
     * @param dir
     */
    private void scanFiles(File dir, StorageInfo storageInfo) {
        if (dir.isFile()) {
            String path = dir.getPath();
            path = path.substring(DataNodeConfig.DATA_DIR.length() - 2);
            // \image\product\iphone.jpg
            path = path.replace("\\\\", "/"); // /image/product/iphone.jpg

            storageInfo.addFilename(path);
            storageInfo.addStoredDataSize(dir.length());

            return;
        }

        File[] children = dir.listFiles();
        if (children == null || children.length == 0) {
            return;
        }

        for (File child : children) {
            scanFiles(child, storageInfo);
        }
    }

    /**
     * 运行DataNode
     */
    private void run() {
        try {
            while (shouldRun) {
                Thread.sleep(10000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        DataNode datanode = new DataNode();
        datanode.initialize();
        datanode.run();
    }

}
